package com.wolfeyes.framework.springsecurity.filter;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.wolfeyes.framework.springsecurity.domain.model.CustomizeLoginBody;
import com.wolfeyes.framework.springsecurity.domain.model.CustomizeUserDetails;
import com.wolfeyes.framework.springsecurity.domain.model.CustomizeUsernamePasswordAuthenticationToken;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @description Spring Security默认的表单登录认证的过滤器是UsernamePasswordAuthenticationFilter，这个过滤器并不适用于前后端分离的架构，因此我们需要自定义一个过滤器。
 * @title 登录认证的filter，参照UsernamePasswordAuthenticationFilter，添加到这之前的过滤器-UsernamePasswordAuthenticationFilter
 * @author yanyljava
 * @create 2022-01-14 21:25
 */
@Slf4j
public class CustomizeJwtAuthenticationLoginFilter extends AbstractAuthenticationProcessingFilter {

	/**
	 * @title 构造方法，调用父类的，设置登录地址/login，请求方式POST
	 */
//	public CustomizeJwtAuthenticationLoginFilter() {
//		super(new AntPathRequestMatcher("/sysUser/login", "POST"));
//	}
	
	public CustomizeJwtAuthenticationLoginFilter(String defaultFilterProcessesUrl, String httpMethod) {
		super(new AntPathRequestMatcher(defaultFilterProcessesUrl, httpMethod));
	}
	
//	protected CustomizeJwtAuthenticationLoginFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {
//		//super(new AntPathRequestMatcher(defaultFilterProcessesUrl));
//		super(new AntPathRequestMatcher(defaultFilterProcessesUrl, "POST"));//httpMethod-POST
//		setAuthenticationManager(authenticationManager);
//	}
	
	protected CustomizeJwtAuthenticationLoginFilter(String defaultFilterProcessesUrl, String httpMethod, AuthenticationManager authenticationManager) {
		//super(new AntPathRequestMatcher(defaultFilterProcessesUrl));
		super(new AntPathRequestMatcher(defaultFilterProcessesUrl, httpMethod));
		setAuthenticationManager(authenticationManager);
	}
	
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
		
		log.debug("自定义的Token登录认证过滤器被调用 Start！");
//		User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
//		return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
		
		//CustomizeLoginBody customizeLoginBody = new ObjectMapper().readValue(request.getInputStream(), CustomizeLoginBody.class);
		CustomizeUsernamePasswordAuthenticationToken customizeUsernamePasswordAuthenticationToken = new ObjectMapper().readValue(request.getInputStream(), CustomizeUsernamePasswordAuthenticationToken.class);
		//获取表单提交数据（获取失败，已废弃~）
		//String userName = request.getParameter("userName");
		//String password = request.getParameter("password");
		//String userName = customizeLoginBody.getUserName();
		//String password = customizeLoginBody.getPassword();
		//封装到token中提交
		//UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userName, password);
		// 该方法会去调用CustomizeUserDetailsService.loadUserByUsername
		//return getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
		//return getAuthenticationManager().authenticate(customizeUsernamePasswordAuthenticationToken);
		Authentication authentication = getAuthenticationManager().authenticate(customizeUsernamePasswordAuthenticationToken);
		log.debug("自定义的Token登录认证过滤器被调用 Start！");
		return authentication;
		
//		try {
//			User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
//			UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword());
//			// 该方法会去调用CustomizeUserDetailsService.loadUserByUsername
//			return getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
//		}catch (Exception e){
//			try {
//				response.setContentType("application/json;charset=utf-8");
//				response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
//				PrintWriter out = response.getWriter();
//				Map resultMap = new HashMap();
//				resultMap.put("code", HttpServletResponse.SC_UNAUTHORIZED);
//				resultMap.put("msg", "用户名或密码错误！");
//				out.write(new ObjectMapper().writeValueAsString(resultMap));
//				out.flush();
//				out.close();
//			}catch (Exception outEx){
//				outEx.printStackTrace();
//			}
//			throw new RuntimeException(e);
//		}

	}
	
	
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
		
		// 该方法会去调用CustomizeAuthenticationSuccessHandler.onAuthenticationSuccess(request, response, authResult);
		super.successfulAuthentication(request, response, chain, authResult);
		
//		CustomizeUserDetails customizeUserDetails = (CustomizeUserDetails)authResult.getPrincipal();
//		Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();
//		StringBuffer as = new StringBuffer();
//		for (GrantedAuthority authority : authorities) {
//			as.append(authority.getAuthority())
//					.append(",");
//		}
//		String jwt = Jwts.builder()
//				.claim("authorities", as)//配置用户角色
//				.setSubject(authResult.getName())
//				.setExpiration(new Date(System.currentTimeMillis() + 10 * 60 * 1000))
//				.signWith(SignatureAlgorithm.HS512,"sang@123")
//				.compact();
//		response.setContentType("application/json;charset=utf-8");
//		PrintWriter out = response.getWriter();
//		out.write(new ObjectMapper().writeValueAsString(jwt));
//		out.flush();
//		out.close();
		
//		UserPojo user = new UserPojo();
//		user.setUsername(authResult.getName());
//		user.setRoles((List<RolePojo>)authResult.getAuthorities());
//		String token = JwtUtils.generateTokenExpireInMinutes(user, prop.getPrivateKey(), 24 * 60);
//		response.addHeader("Authorization", "Bearer "+token);
//		try {
//			response.setContentType("application/json;charset=utf-8");
//			response.setStatus(HttpServletResponse.SC_OK);
//			PrintWriter out = response.getWriter();
//			Map resultMap = new HashMap();
//			resultMap.put("code", HttpServletResponse.SC_OK);
//			resultMap.put("msg", "认证通过！");
//			out.write(new ObjectMapper().writeValueAsString(resultMap));
//			out.flush();
//			out.close();
//		}catch (Exception outEx){
//			outEx.printStackTrace();
//		}
		
	}
	
	@Override
	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
		
		// 该方法会去调用CustomizeAuthenticationFailureHandler.onAuthenticationFailure(request, response, failed);
		super.unsuccessfulAuthentication(request, response, failed);
		
//		resp.setContentType("application/json;charset=utf-8");
//		PrintWriter out = resp.getWriter();
//		out.write("登录失败!");
//		out.flush();
//		out.close();
	}
	
}

